package cn.wostore.wxhelper.Xposed;

import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import cn.wostore.wxhelper.bean.PackageNameInfo;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;

import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.List;

/**
 * @author wuch
 * @date 2018/12/19 0019
 */
public class LoadHook {
    Activity launcherUI;
    public PackageNameInfo info = new PackageNameInfo();
    final ClassLoader classLoader;
    String dbPath;

    public LoadHook(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    public void mainLoad(ClassLoader classLoader) {
        try {
            copyDatabase(classLoader);
        } catch (Throwable th) {
            log(th);
        }
        try {
            addButtonHook(classLoader);
        } catch (Throwable th) {
            log(th);
        }
        try {
            getActivity(classLoader);
        } catch (Throwable th) {
            log(th);
        }
//        try {
//            hookTest(classLoader);
//        } catch (Throwable th) {
//            log(th);
//        }
        try {
            hookDatabaseInsert(classLoader);
        } catch (Throwable th) {
            log(th);
        }
        try {
            hookAppUpdater(classLoader);
        } catch (Throwable th) {
            log(th);
        }

//        try {
//            hookDatabaseUpdate(classLoader);
//        } catch (Throwable th) {
//            log(th);
//        }

    }

    public void a(final Object obj, final String str) {
        XposedHelpers.findAndHookMethod("com.tencent.mm.ui.chatting.viewitems.c$c$a", classLoader, "onMMMenuItemSelected",
                MenuItem.class, int.class,
                new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        super.afterHookedMethod(param);
                        MenuItem item = (MenuItem) param.args[0];
                        String title = item.getTitle().toString();
                        log(title);
                        if (title.equals("哈哈哈")) {
                            openSelectContactUI(obj, str);
//                            Uri uri = Uri.parse("content://cn.wostore.wxhelper.provider/ForwardObj");
//                            ContentValues contentValues = new ContentValues();
//                            contentValues.put("forwardRuleId", 1);
//                            contentValues.put("forwardObjId", 12);
//                            contentValues.put("forwardObjTitle", "das");
//                            contentValues.put("forwardObjIcon", "dsadsads");
//                            contentValues.put("forwardObjGroup", true);
//                            contentValues.put("forwardObjType", 1);
//                            launcherUI.getContentResolver().insert(uri, contentValues);
//                            log(launcherUI.getContentResolver().getType(uri));
                        }
                    }
                });
    }

    /**
     * 测试Hook
     */
    private void hookTest(final ClassLoader classLoader) {
        Class<?> clazzb = XposedHelpers.findClassIfExists("com.tencent.mm.ui.transmit.MsgRetransmitUI$b", classLoader);
        XposedHelpers.findAndHookMethod(
                "com.tencent.mm.ui.transmit.MsgRetransmitUI",
                classLoader,
                "a",
                clazzb,
                String.class,
                new XC_MethodHook() {

                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        log("com.tencent.mm.ui.transmit.MsgRetransmitUI.a 执行栈开始");
                        StackTraceElement[] stackTrace = new Throwable().getStackTrace();
                        if (stackTrace != null){
                            log(Arrays.toString(stackTrace));
                        }
                        log("com.tencent.mm.ui.transmit.MsgRetransmitUI.a 执行栈结束");
                        log(Arrays.toString(param.args));
                    }
                });

    }

    /**
     * 测试微信自动更新，阻止微信自动更新
     */
    private void hookAppUpdater (ClassLoader classLoader) {
        XposedHelpers.findAndHookMethod(
                "com.tencent.mm.sandbox.updater.AppUpdaterUI",
                classLoader,
                "onCreate",
                Bundle.class,
                new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        StackTraceElement[] stackTrace = new Throwable().getStackTrace();
                        if (stackTrace != null){
                            log(Arrays.toString(stackTrace));
                        }
                        log(Arrays.toString(param.args));
                        log(param.thisObject.toString());
                        XposedHelpers.callMethod(param.thisObject, "cpK");
                    }
                });

    }


    /**
     * 拦截微信的数据库增加
     *
     * @param classLoader
     */
    private void hookDatabaseInsert(ClassLoader classLoader) {
        XposedHelpers.findAndHookMethod(info.WX_DATABASE, classLoader, "insertWithOnConflict",
                String.class, String.class, ContentValues.class, int.class, new DatabaseInsertHook(this));
    }

    /**
     * 拦截微信数据库更新
     *
     * @param classLoader
     */
    private void hookDatabaseUpdate(ClassLoader classLoader) {
        XposedHelpers.findAndHookMethod(info.WX_DATABASE, classLoader, "updateWithOnConflict",
                String.class, ContentValues.class, String.class, String[].class, int.class, new DatabaseUpdateHook(this));
    }

    /**
     * 拷贝微信的本地数据库
     *
     * @param classLoader
     */
    private void copyDatabase(ClassLoader classLoader) {
        Class classVar = XposedHelpers.findClassIfExists(info.WX_DATABASE, classLoader);
        Class param1 = XposedHelpers.findClassIfExists(info.WX_DATABASE_PARAM1, classLoader);
        Class param2 = XposedHelpers.findClassIfExists(info.WX_DATABASE_PARAM2, classLoader);
        XposedHelpers.findAndHookConstructor(classVar,
                String.class, int.class, param1, param2, new CopyDatabaseHook(this));
    }

    /**
     * 聊天界面的消息菜单增加功能按钮
     *
     * @param classLoader
     */
    private void addContextMenuItem(ClassLoader classLoader) {
        hookByConstructor(info.CHAT_ITEM, classLoader, info.CHAT_VIEW_ITEM, info.CHAT_MAIN, new AddMenuItemHook(this));
    }


    /**
     * 获取微信群组的名字和ID
     *
     * @param classLoader
     */
    void getGroupList(ClassLoader classLoader) {
        Class cls = XposedHelpers.findClassIfExists(info.GET_GROUP, classLoader);
        List list = (List) XposedHelpers.callStaticMethod(cls, "GV");
        for (Object obj : list) {
            XposedBridge.log(XposedHelpers.getObjectField(obj, "field_nickname").toString() +
                    XposedHelpers.getObjectField(obj, "field_username").toString());
        }
    }

    /**
     * 打印错误日志
     *
     * @param th 错误信息
     */
    private static void log(Throwable th) {
        XposedBridge.log(th);
    }

    /**
     * 打印字符串输出
     *
     * @param str
     */
    private static void log(String str) {
        XposedBridge.log(str);
    }

    /**
     * 给微信内部添加插件入口，暂时保留，可能会去除这个功能
     *
     * @param classLoader
     */
    private void addButtonHook(ClassLoader classLoader) {
        XposedHelpers.findAndHookMethod(info.LAUNCHER_UI, classLoader,
                "onCreateOptionsMenu", Menu.class, new AddButtonHook());
        XposedHelpers.findAndHookMethod(info.LAUNCHER_UI, classLoader,
                "onOptionsItemSelected", MenuItem.class, new StartMainActivityHook(this));
    }

    /**
     * 获取微信主界面UI 的activity实例
     *
     * @param classLoader
     */
    private void getActivity(ClassLoader classLoader) {
        //XposedHelpers.findAndHookMethod(info.LAUNCHER_UI,classLoader,"onCreate",Bundle.class,new IntentHook(this));
        XposedHelpers.findAndHookMethod(info.LAUNCHER_UI, classLoader, "onResume", new GetActivityHook(this, classLoader));
    }

    public void openSelectContactUI(Object obj, String str) {
        if (!TextUtils.isEmpty(str)) {
            try {
                XposedBridge.log(str);
                Intent intent = new Intent();
                intent.setClassName(this.launcherUI.getApplicationContext(), this.info.SELECT_CONVERSATION);
                intent.putExtra("Select_Talker_Name", str);
                intent.putExtra("Select_block_List", str);
                intent.putExtra("Select_Conv_Type", 3);
                intent.putExtra("Select_Send_Card", false);
                XposedHelpers.callMethod(obj, "startActivityForResult", intent, 1000);
            } catch (Throwable th) {
                log(th);
            }
        }

    }

    private static void hookByConstructor(String str, ClassLoader classLoader, Object... objArr) {
        Class findClass = XposedHelpers.findClass(str, classLoader);
        Class[] clsArr = new Class[(objArr.length - 1)];
        int i = 0;
        while (true) {
            int i2 = i;
            if (i2 < objArr.length - 1) {
                if (objArr[i2] instanceof String) {
                    clsArr[i2] = XposedHelpers.findClass((String) objArr[i2], classLoader);
                } else if (objArr[i2] instanceof Class) {
                    clsArr[i2] = (Class) objArr[i2];
                }
                i = i2 + 1;
            } else {
                try {
                    Constructor declaredConstructor = findClass.getConstructor(clsArr);
                    declaredConstructor.setAccessible(true);
                    XposedBridge.hookMethod(declaredConstructor, (XC_MethodHook) objArr[objArr.length - 1]);
                    return;
                } catch (Throwable th) {
                    XposedBridge.log(th);
                    return;
                }
            }
        }

    }
}
